package com.edu.system.service.impl;

import com.edu.common.exception.ServiceException;
import com.edu.common.exception.xxxx.BalanceException;
import com.edu.common.exception.xxxx.CardLossException;
import com.edu.common.exception.xxxx.CardNotExistsException;
import com.edu.common.utils.DictUtils;
import com.edu.common.utils.SecurityUtils;
import com.edu.common.utils.StringUtils;
import com.edu.common.utils.bean.BeanValidators;
import com.edu.common.utils.uuid.Seq;
import com.edu.system.domain.*;
import com.edu.system.domain.dto.BalanceStatDTO;
import com.edu.system.service.*;

import java.util.Date;
import java.util.List;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Resource;
import javax.validation.Validator;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.edu.system.mapper.TCardMapper;
import org.springframework.transaction.annotation.Transactional;

/**
 * 卡管理Service业务层处理
 *
 * @author xxxx
 * @date 2023-12-17
 */
@Slf4j
@Service
public class TCardServiceImpl implements ITCardService {
    @Autowired
    private TCardMapper tCardMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    protected Validator validator;

    @Autowired
    private ITChargeRecordService chargeRecordService;

    @Autowired
    private ITRechargeRecordService rechargeRecordService;
    @Resource
    private IStudentService iStudentService;
    @Resource
    private ITClassService itClassService;

    @Resource
    private ITTeacherService teacherService;

    private static final Integer STATUS_0 = 0;
    private static final Integer STATUS_1 = 1;
    private static final Integer IS_DELETED_0 = 0;
    private static final Integer IS_DELETED_1 = 1;

    /**
     * 查询卡管理
     *
     * @param id 卡管理主键
     * @return 卡管理
     */
    @Override
    public TCard selectTCardById(Long id) {
        return tCardMapper.selectTCardById(id);
    }

    /**
     * 查询卡管理列表
     *
     * @param tCard 卡管理
     * @return 卡管理
     */
    @Override
    public List<TCard> selectTCardList(TCard tCard) {
        tCard.setIsDeleted(0);
        List<TCard> list = tCardMapper.selectTCardList(tCard);
        Map<Long, String> classMap = itClassService
            .selectIdNameMap(list.stream().map(TCard::getClassId).collect(Collectors.toList()));
        for (TCard card : list) {
            card.setClassName(classMap.getOrDefault(card.getClassId(), ""));
        }
        return list;
    }

    @Override
    public List<TCard> selectCardByIds(List<Long> ids) {
        List<TCard> list = tCardMapper.selectListByIds(ids);

        Map<Long, String> classMap = itClassService
            .selectIdNameMap(list.stream().map(TCard::getClassId).collect(Collectors.toList()));
        for (TCard card : list) {
            card.setClassName(classMap.getOrDefault(card.getClassId(), ""));
        }
        return list;
    }

    /**
     * 新增卡管理
     *
     * @param tCard 卡管理
     * @return 结果
     */
    @Override
    public int insertTCard(TCard tCard) {
        // 生成个唯一lineNo
        tCard.setLineNo("line-" + Seq.generateNo());
        String ownerId = tCard.getOwnerId();
        // 学生卡
        if(isStudentCard(tCard)){
            Student student = iStudentService.selectStudentByStuNo(ownerId);
            tCard.setGeneration(student.getGeneration());
            tCard.setOwner(student.getName());
            tCard.setClassId(student.getClassId());
        }else{
            // 教师卡
            TTeacher teacher = teacherService.selectByEmployeeId(ownerId);
            tCard.setOwner(teacher.getName());
        }

        return tCardMapper.insertTCard(tCard);
    }

    public boolean isStudentCard(TCard tCard){
        return TCard.type_student == tCard.getType();
    }

    /**
     * 修改卡管理
     *
     * @param tCard 卡管理
     * @return 结果
     */
    @Override
    public int updateTCard(TCard tCard) {
        return tCardMapper.updateTCard(tCard);
    }

    /**
     * 批量删除卡管理
     *
     * @param ids 需要删除的卡管理主键
     * @return 结果
     */
    @Override
    public int deleteTCardByIds(Long[] ids) {

        Stream.of(ids).forEach(this::deleteTCardById);
        return 1;
    }

    /**
     * 删除卡管理信息
     *
     * @param id 卡管理主键
     * @return 结果
     */
    @Override
    public int deleteTCardById(Long id) {
        TCard c = new TCard();
        c.setId(id);
        c.setIsDeleted(IS_DELETED_1);
        c.setStatus(STATUS_1);
        c.setBalance((float) 0);
        return tCardMapper.updateTCard(c);
    }

    @Override
    public String importCard(List<TCard> list, Integer cardType) {
        if (StringUtils.isNull(list) || list.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }
        AtomicInteger successNum = new AtomicInteger();
        AtomicInteger failureNum = new AtomicInteger();
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        list.parallelStream().forEach(c -> {
            try {
                BeanValidators.validateWithException(validator, c);
                // 验证是否存在
                TCard card = this.findCardByNo(c.getCardNo());
                Student student = iStudentService.checkIsExist(c.getOwner(), c.getOwnerId());
                if (StringUtils.isNull(card) && StringUtils.isNotNull(student)) {
                    c.setType(cardType);
                    this.insertTCard(c);
                    successNum.getAndIncrement();
                    successMsg.append("<br/>" + successNum + "、" + c.getOwner() + " 卡导入成功");
                } else if (StringUtils.isNotNull(card)){
                    failureNum.getAndIncrement();
                    failureMsg.append("<br/>" + failureNum + "、" + c.getOwner() + " 卡已存在");
                } else {
                    failureNum.getAndIncrement();
                    failureMsg.append("<br/>" + failureNum + "、学生 " + c.getOwner() + " 不存在");
                }
            } catch (Exception e) {
                failureNum.getAndIncrement();
                String msg = "<br/>" + failureNum + "、" + c.getOwner() + " 卡导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        });

        if (failureNum.get() > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public TCard checkIsExist(String owner, Long classId) {
        TCard t = new TCard();
        t.setOwner(owner);
        t.setClassId(classId);
        t.setStatus(STATUS_0);
        t.setIsDeleted(0);
        List<TCard> list = tCardMapper.selectTCardList(t);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    @Override
    public TCard checkIsExist(String ownerId, String owner) {
        TCard t = new TCard();
        t.setOwnerId(ownerId);
        t.setOwner(owner);
        t.setStatus(STATUS_0);
        t.setIsDeleted(0);
        List<TCard> list = tCardMapper.selectTCardList(t);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    @Override
    public TCard findCardByNo(String cardNo) {
        TCard t = new TCard();
        t.setCardNo(cardNo);
        t.setIsDeleted(0);
        List<TCard> list = tCardMapper.selectTCardList(t);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    @Override
    public TCard findCardByOwnerId(String ownerId) {
        TCard t = new TCard();
        t.setOwnerId(ownerId);
        t.setIsDeleted(0);
        List<TCard> list = tCardMapper.selectTCardList(t);
        if (CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    @Override
    @Transactional
    public Long replaceCard(String newCardNo, Long oldCardId) {

        TCard card = tCardMapper.selectTCardById(oldCardId);
        // 删除老卡
        this.deleteTCardById(oldCardId);
        // 补卡 继承原卡所有属性
        card.setId(null);
        card.setCardNo(newCardNo);
        tCardMapper.insertTCard(card);
        return card.getId();
    }

    /**
     * 消费
     * @param cardNo
     * @param amount
     * @return
     */
    @Override
    public TCard charge(String cardNo, Float amount) {
        TCard card = tCardMapper.selectTCardByCardNo(cardNo);
        if(card == null){
            throw new CardNotExistsException(cardNo+" not exists");
        }
        Float balance = card.getBalance();
        if(balance-amount<0){
            throw new BalanceException(cardNo+" 余额不足");
        }
        if (card.getStatus().equals(STATUS_1)){
            throw new CardLossException("该卡已被挂失，不能消费");
        }
        card.setBalance(balance-amount);
        tCardMapper.updateBalance(card);
        this.saveTChargeRecord(card,amount);
        return card;
    }

    /**
     * 充值
     * @param cardNos
     * @param amount
     * @return
     */
    @Override
    @Transactional
    public int recharge(List<String> cardNos, Float amount) {
        int counter=0;
        for (String cardNo : cardNos) {
            TCard card = tCardMapper.selectTCardByCardNo(cardNo);
            if(card == null){
                throw new CardNotExistsException(cardNo+" not exists");
            }
            card.setBalance(card.getBalance()+amount);
            if (card.getBalance() < 0){
                throw new CardNotExistsException(cardNo + " 充值后，用户余额不能为负");
            }
            tCardMapper.updateBalance(card);
            this.saveTRechargeRecord(card,amount);
            counter++;
        }

        return counter;
    }

    @Override
    public BalanceStatDTO cntBalance(Integer balance) {
        long cnt = tCardMapper.cntBetweenBalance(null, null);
        long warnCnt = tCardMapper.cntBetweenBalance(0, balance);
        return BalanceStatDTO.builder()
            .warnCnt(Integer.parseInt(String.valueOf(warnCnt)))
            .otherCnt(Integer.parseInt(String.valueOf(cnt - warnCnt)))
            .build();
    }


    private void saveTRechargeRecord(TCard card,Float amount){
        TRechargeRecord rechargeRecord = createRechargeRecord(card, amount);
        this.rechargeRecordService.insertTRechargeRecord(rechargeRecord);
    }

    private void saveTChargeRecord(TCard card,Float amount){
        TChargeRecord chargeRecord = createChargeRecord(card, amount);
        this.chargeRecordService.insertTChargeRecord(chargeRecord);
    }


    private TRechargeRecord createRechargeRecord(TCard card,Float amount){
        TRechargeRecord record = new TRechargeRecord();
        record.setOwnerType(DictUtils.getDictLabel("t_card_type", card.getType().toString()));
        record.setCardNo(card.getCardNo());
        record.setLineNo(card.getLineNo());
        record.setAmount(amount);
        record.setOwnerId(card.getOwnerId());
        record.setOwnerName(card.getOwner());
        record.setCreateBy(SecurityUtils.getUsername());
        return record;
    }

    //FIXME: 这里还要修改
    private TChargeRecord createChargeRecord(TCard card,Float amount){
        TChargeRecord record = new TChargeRecord();
        record.setAmount(amount);
        record.setBalance(card.getBalance());
        record.setCardNo(card.getCardNo());
        record.setChargeTime(new Date());
//        record.setChargeType();
//        record.setBillNo();
        record.setOwnerId(card.getOwnerId());
        record.setOwnerName(card.getOwner());
        record.setCreateBy(SecurityUtils.getUsername());
        record.setCreateTime(new Date());
        return record;
    }

}
